#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/sem.h>

/* 利用信号量让相同进程在系统每时每刻只有一个运行实例 */
int main ()
{
	FILE *fp = NULL;
	char *filename = "single"; // 文件不能删除掉，unp v2说过这个问题

	fp = fopen(filename, "a");
	if (NULL == fp)
		return -1;
	fclose(fp);

	key_t key = ftok(filename, 1);

	union semun {
		int val;
		struct semid_ds *buf;
		unsigned short *array;
	};

	union semun sem_union;
	sem_union.val = 1;
	int result;
	int sem_id;
	sem_id = semget(key, 1, 0666 | IPC_EXCL); //首先尝试获取信号量的id

	if (-1 == sem_id)
	{
		//信号量还没有创建，第一次执行这个程序
		sem_id = semget(key, 1, 0666 | IPC_CREAT  | IPC_EXCL); // 原子创建一个信号量
		if (-1 == sem_id)
		{
			perror("semget");
			return -1;
		}

		result = semctl(sem_id, 0, SETVAL, sem_union); //设置信号量的初始值

		if (-1 == result)
		{
			perror("semctl");
			return -1;
		}
	}

	struct sembuf sem_b;
	sem_b.sem_num = 0;
	sem_b.sem_op = -1;
	sem_b.sem_flg = SEM_UNDO;

	struct timespec timeout;
	timeout.tv_sec = 1;
	timeout.tv_nsec = 0;
	
	// semop
	if (-1 == semtimedop(sem_id, &sem_b, 1, &timeout)) //尝试获取信号量，超时时间为1秒，超时则表示进程已经存在。
	{
		perror("same process exist");
		return -1;
	}

	sleep(100);
	return 0;
}
